<!doctype html>



  


<html class="theme-next mist use-motion" lang="zh-Hans">
<head>
  <meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>



<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />















  
  
  <link href="/blog/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css" />




  
  
  
  

  
    
    
  

  

  

  

  

  
    
    
    <link href="//fonts.googleapis.com/css?family=Lato:300,300italic,400,400italic,700,700italic&subset=latin,latin-ext" rel="stylesheet" type="text/css">
  






<link href="/blog/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css" />

<link href="/blog/css/main.css?v=5.1.0" rel="stylesheet" type="text/css" />


  <meta name="keywords" content="java,jvm," />








  <link rel="shortcut icon" type="image/x-icon" href="/blog/favicon.ico?v=5.1.0" />






<meta name="description" content="JVM参数JVM各个参数的含义 Xms：jvm最小内存 Xmx：jvm最大内存通常当jvm内存小于40%（可通过-XX:MinHeapFreeRatio来设置）时，会将jvm内存设为Xmx。而当空余内存大于可用内存的70%（-XX:MaxHeapFreeRatio来设置）时，将内存大小设为Xms。所以为了减少内存容量频繁变化，将Xms和Xmx设为一样大小 -XX:PermSize 、-XX:Max">
<meta name="keywords" content="java,jvm">
<meta property="og:type" content="article">
<meta property="og:title" content="JVM随记">
<meta property="og:url" content="https://gitee.com/shuhao/2017/12/23/JVM随记/index.html">
<meta property="og:site_name" content="Niki">
<meta property="og:description" content="JVM参数JVM各个参数的含义 Xms：jvm最小内存 Xmx：jvm最大内存通常当jvm内存小于40%（可通过-XX:MinHeapFreeRatio来设置）时，会将jvm内存设为Xmx。而当空余内存大于可用内存的70%（-XX:MaxHeapFreeRatio来设置）时，将内存大小设为Xms。所以为了减少内存容量频繁变化，将Xms和Xmx设为一样大小 -XX:PermSize 、-XX:Max">
<meta property="og:locale" content="zh-Hans">
<meta property="og:image" content="https://gitee.com/blog/images/java/jvm/gc_sign_clean_1.jpg">
<meta property="og:image" content="https://gitee.com/blog/images/java/jvm/gc_sign_clean_2.jpg">
<meta property="og:image" content="https://gitee.com/blog/images/java/jvm/gc_copy_1.jpg">
<meta property="og:image" content="https://gitee.com/blog/images/java/jvm/gc_copy_2.jpg">
<meta property="og:image" content="https://gitee.com/blog/images/java/jvm/gc_sign_arrangement_1.jpg">
<meta property="og:image" content="https://gitee.com/blog/images/java/jvm/gc_arrangement_2.jpg">
<meta property="og:image" content="https://gitee.com/blog/images/java/jvm/class_live.jpg">
<meta property="og:image" content="https://gitee.com/blog/images/java/jvm/thread_monitor.bmp">
<meta property="og:image" content="https://gitee.com/blog/images/java/jvm/jvm_heap_dump_1.png">
<meta property="og:updated_time" content="2018-08-06T09:33:11.386Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="JVM随记">
<meta name="twitter:description" content="JVM参数JVM各个参数的含义 Xms：jvm最小内存 Xmx：jvm最大内存通常当jvm内存小于40%（可通过-XX:MinHeapFreeRatio来设置）时，会将jvm内存设为Xmx。而当空余内存大于可用内存的70%（-XX:MaxHeapFreeRatio来设置）时，将内存大小设为Xms。所以为了减少内存容量频繁变化，将Xms和Xmx设为一样大小 -XX:PermSize 、-XX:Max">
<meta name="twitter:image" content="https://gitee.com/blog/images/java/jvm/gc_sign_clean_1.jpg">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/blog/',
    scheme: 'Mist',
    sidebar: {"position":"right","display":"post","offset":12,"offset_float":0,"b2t":false,"scrollpercent":false},
    fancybox: true,
    motion: true,
    duoshuo: {
      userId: '0',
      author: '博主'
    },
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="https://gitee.com/shuhao/2017/12/23/JVM随记/"/>





  <title> JVM随记 | Niki </title>
</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans">

  





  <script type="text/javascript">
    var _hmt = _hmt || [];
    (function() {
      var hm = document.createElement("script");
      hm.src = "https://hm.baidu.com/hm.js?cb9f0585e406f878cb2f29c89ad3cdb7";
      var s = document.getElementsByTagName("script")[0];
      s.parentNode.insertBefore(hm, s);
    })();
  </script>










  
  
    
  

  <div class="container one-collumn sidebar-position-right page-post-detail ">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/blog/"  class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">Niki</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
      
        <p class="site-subtitle">天道酬勤</p>
      
  </div>

  <div class="site-nav-toggle">
    <button>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/blog/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br />
            
            首页
          </a>
        </li>
      
        
        <li class="menu-item menu-item-categories">
          <a href="/blog/categories" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-categories"></i> <br />
            
            分类
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/blog/archives" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br />
            
            归档
          </a>
        </li>
      
        
        <li class="menu-item menu-item-tags">
          <a href="/blog/tags" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-tags"></i> <br />
            
            标签
          </a>
        </li>
      

      
    </ul>
  

  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  

  
  
  

  <article class="post post-type-normal " itemscope itemtype="http://schema.org/Article">
    <link itemprop="mainEntityOfPage" href="https://gitee.com/shuhao/blog/2017/12/23/JVM随记/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="Fang ShuHao">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/blog/images/head.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Niki">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
            
            
              
                JVM随记
              
            
          </h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2017-12-23T11:07:34+08:00">
                2017-12-23
              </time>
            

            

            
          </span>

          
            <span class="post-category" >
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">分类于</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/blog/categories/java/" itemprop="url" rel="index">
                    <span itemprop="name">java</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    


    <div class="post-body" itemprop="articleBody">

      
      

      
        <h2 id="JVM参数"><a href="#JVM参数" class="headerlink" title="JVM参数"></a>JVM参数</h2><h3 id="JVM各个参数的含义"><a href="#JVM各个参数的含义" class="headerlink" title="JVM各个参数的含义"></a>JVM各个参数的含义</h3><ol>
<li>Xms：jvm最小内存</li>
<li>Xmx：jvm最大内存<br>通常当jvm内存小于40%（可通过-XX:MinHeapFreeRatio来设置）时，会将jvm内存设为Xmx。而当空余内存大于可用内存的70%（-XX:MaxHeapFreeRatio来设置）时，将内存大小设为Xms。所以为了减少内存容量频繁变化，将Xms和Xmx设为一样大小</li>
<li>-XX:PermSize 、-XX:MaxPermSize：设置方法去的大小</li>
<li>-XX:SurvivorRation：新生代中Eden区与Survivor区域的大小比值。新生代中有<strong>1个Eden区和2个Survivor区域组成</strong> </li>
<li>–Xmm：新生代的大小</li>
<li>–XX:PretenureSizeThreshold：设置直接进入老年代的对象的大小。单位为字节。</li>
<li>–XX:MaxTenuringThreshold：设置对象经过多少次Minor GC后进入老年代。默认为15</li>
</ol>
<h3 id="JVM调优"><a href="#JVM调优" class="headerlink" title="JVM调优"></a>JVM调优</h3><h2 id="java-YoungGen、OldGen、PermGen"><a href="#java-YoungGen、OldGen、PermGen" class="headerlink" title="java YoungGen、OldGen、PermGen"></a>java YoungGen、OldGen、PermGen</h2><h3 id="年轻代-YoungGen"><a href="#年轻代-YoungGen" class="headerlink" title="年轻代 YoungGen"></a>年轻代 YoungGen</h3><p>年轻代中为新生成的很快被回收的，或者不是很大的对象。新生代中分为三个区：Eden，survivor1，survivor2 。大小比为8:1:1。新生代中进行的GC为：<strong><em>MinorGC</em></strong>。采用的垃圾收集算法为<strong><em>复制算法</em></strong>。</p>
<ul>
<li>垃圾收集过程：<br>对象保存在Eden和survivor1中，发生MinorGC时，将Eden和Survivor1中存货的对象复制到survivor2中，然后对Eden和Survivor1进行清空。</li>
</ul>
<h3 id="老年代-OldGen"><a href="#老年代-OldGen" class="headerlink" title="老年代 OldGen"></a>老年代 OldGen</h3><p>老年代存储特别大的对象，以及历经好几次回收仍存货的对象。老年代中进行的GC为<strong><em>Major GC</em></strong>,和<strong><em>Full GC</em></strong>一样会造成STW（stop-the-world）。老年代采用的垃圾回收算法为<strong><em>标记整理 /标记清除</em></strong> 算法。</p>
<ul>
<li>垃圾收集过程</li>
</ul>
<ol>
<li>进行垃圾回收时，遍历老年代中的对象，对存活对象进行标记，然后将没有标记的回收对象进行删除。这就是<strong><em>标记清除算</em></strong>法，这样会造成很多的内存碎片，浪费宝贵的内存空间。</li>
<li><strong><em>标记整理算法</em></strong>将存活的对象移动到连续的内存空间，让后将其他空间删除。这样避免了产生不连续的内存碎片，造成内存空间的浪费。</li>
</ol>
<h3 id="永久代-PermGen"><a href="#永久代-PermGen" class="headerlink" title="永久代 PermGen"></a>永久代 PermGen</h3><p>永久代用来保存类加载数据，静态变量，常量。该区域不易进行回收。该区域GC为<strong><em>Full GC</em></strong></p>
<ol>
<li>默认大小64M，可通过参数-XX:MaxPermSize来设置。当类信息容量超过MaxPermSize大小，会抛出OOM异常。</li>
<li>perm主要用来保存类的加载类元信息,常量等。（符号引用，字面量，类静态变量）<br><em>从JDK7开始永久代的移除工作，贮存在永久代的一部分数据已经转移到了Java Heap或者是Native Heap。但永久代仍然存在于JDK7，并没有完全的移除：符号引用(Symbols)转移到了native heap;字面量(interned strings)转移到了java heap;类的静态变量(class statics)转移到了java heap。</em></li>
<li>perm和老年代一同进行GC，无论perm和老年代谁满了，都会触犯perm和old generation的GC。</li>
</ol>
<h2 id="java-heap-堆"><a href="#java-heap-堆" class="headerlink" title="java heap 堆"></a>java heap 堆</h2><p>保存java对象的区域。主要分为：年轻代和老年代。</p>
<h2 id="CodeCache"><a href="#CodeCache" class="headerlink" title="CodeCache"></a>CodeCache</h2><ol>
<li>java代码编译后的机器码<br>java代码在执行时一旦被编译器便以为机器码，下一次执行的时候就会直接执行编译后的代码，也就是说，编译后的代码被缓存起来。缓存变异后的机器码的内存区域就是codeCache。<br>这也是为什么代码修改后需要重启JVM</li>
<li>jni编译的本地代码</li>
</ol>
<h3 id="JVM-编译模式"><a href="#JVM-编译模式" class="headerlink" title="JVM 编译模式"></a>JVM 编译模式</h3><ol>
<li><p>解释执行<br>不经过JIT直接由解释器解释所有的字节码，执行效率不高。</p>
</li>
<li><p>混合模式（mixed mode） 默认<br><strong>判断热点代码</strong>（多次调用等），JVM会将其编译成机器码以提高执行效率，对于非热点代码，则在解释模式下执行。减少编译和优化成本。<br>混合模式是jvm默认的编译模式</p>
</li>
<li><p>编译模式<br>将全部代码的字节码编译成机器码，不论代码是否有编译价值。虽然绕开了缓慢的解释器，但是会缓存所有代码的机器码，会有性能损失。</p>
</li>
</ol>
<h3 id="JIT编译"><a href="#JIT编译" class="headerlink" title="JIT编译"></a>JIT编译</h3><p>JIT（just-in-compiler）即使编译器。<br>把java的<strong>字节码</strong>转换成可以直接发送给处理器的指令的程序。</p>
<h4 id="编译参数"><a href="#编译参数" class="headerlink" title="编译参数"></a>编译参数</h4><ul>
<li>-Xcomp jvm运行在纯编译模式</li>
<li>-Xint jvm运行在纯解释模式</li>
<li>-XX:+TieredCompilation 开启JVM分层编译模式</li>
<li>-XX:ReservedCodeCacheSize=256M 设置codeCache大小</li>
<li>-XX:+PrintCodeCache jvm停止时打印codeCache使用情况</li>
</ul>
<h3 id="Java对象创建的过程"><a href="#Java对象创建的过程" class="headerlink" title="Java对象创建的过程"></a>Java对象创建的过程</h3><ol>
<li>编译器通过逃逸分析，确定对象是在栈上分配还是在堆上分配。如果是在堆上分配，则进入选项2.</li>
<li>如果tlab_top + size &lt;= tlab_end，则在在TLAB上直接分配对象并增加tlab_top 的值，如果现有的TLAB不足以存放当前对象则3.</li>
<li>重新申请一个TLAB，并再次尝试存放当前对象。如果放不下，则4.</li>
<li>在Eden区加锁（这个区是多线程共享的），如果eden_top + size &lt;= eden_end则将对象存放在Eden区，增加eden_top 的值，如果Eden区不足以存放，则5.</li>
<li>执行一次Young GC（minor collection）。</li>
<li>经过Young GC之后，如果Eden区任然不足以存放当前对象，则直接分配到老年代。</li>
</ol>
<h2 id="jdk8去掉PermGen新增Metaspace的好处"><a href="#jdk8去掉PermGen新增Metaspace的好处" class="headerlink" title="jdk8去掉PermGen新增Metaspace的好处"></a>jdk8去掉PermGen新增Metaspace的好处</h2><ol>
<li>在HotSpot中每个垃圾收集器需要对PermGen做专门的代码处理来收集PermGen中的类的元数据信息。而Metaspace的分配具有和Heap相同的地址空间，因此，Metaspace和Java Heap可以无缝管理，简化Full GC的过程。</li>
<li>一定程度上消灭了OOM异常。Metaspace使用本地内存，类元数据只要不超过native memory即可。<br><em>Native Heap，就是C-Heap。对于32位的JVM，C-Heap的容量=4G-Java Heap-PermGen；对于64位的JVM，C-Heap的容量=物理服务器的总RAM+虚拟内存-Java Heap-PermGen，在Windows下称为虚拟内存(virtual memory),在Linux下称为交换空间(swap space),用于当系统需要更多的内存资源而物理内存已经满了的情况下，将物理内存中不活跃的页转移到磁盘上的交换空间。</em></li>
</ol>
<h2 id="Metaspace的不足"><a href="#Metaspace的不足" class="headerlink" title="Metaspace的不足"></a>Metaspace的不足</h2><p>因为Metaspace将类元数据存储在一个块（chunk）中（Metaspace中通过<em>块分配器</em>来管理Metaspace空间。）但是类大小不固定，所以类元数据的大小也不固定，然而块chunk的大小取决于类加载器的类型。所以难免会存在类元数据与块大小不想等，造成内存碎片的问题。且Metaspace还没有使用压缩技术。</p>
<h2 id="垃圾收集算法"><a href="#垃圾收集算法" class="headerlink" title="垃圾收集算法"></a>垃圾收集算法</h2><h3 id="标记清除算法"><a href="#标记清除算法" class="headerlink" title="标记清除算法"></a>标记清除算法</h3><p>将被回收的对象进行标记，然后统一清除被标记的对象。<br>该GC算法主要缺点：</p>
<ol>
<li>标记和清除过程效率不高</li>
<li>产生大量的内存碎片，造成内存的浪费<img src="/blog/images/java/jvm/gc_sign_clean_1.jpg">
<img src="/blog/images/java/jvm/gc_sign_clean_2.jpg">
</li>
</ol>
<h3 id="复制算法"><a href="#复制算法" class="headerlink" title="复制算法"></a>复制算法</h3><p>将内存分为两份，一份为使用内存，另一份为备用内存。GC过程中，将目前存活的对象从使用内存拷贝到备用内存，从而将备用内存改为使用内存，之前的使用内存改为备用内存，以备下次GC使用。<br>该GC算法实现简单，运行高效；解决了内存碎片的问题；但是实际可用内存大小减半。<br><img src="/blog/images/java/jvm/gc_copy_1.jpg"><br><img src="/blog/images/java/jvm/gc_copy_2.jpg"></p>
<h3 id="标记整理算法"><a href="#标记整理算法" class="headerlink" title="标记整理算法"></a>标记整理算法</h3><p>标记过程与标记清除算法一致，而在清理对象完成后，让所有存活对象都向一端移动，并更新引用其对象的指针。<br>虽然该算法不会产生内存碎片，但是对象移动的成本比较高。<br><img src="/blog/images/java/jvm/gc_sign_arrangement_1.jpg"><br><img src="/blog/images/java/jvm/gc_arrangement_2.jpg"></p>
<p>三种垃圾回收算法比较</p>
<ul>
<li><p>效率：复制算法&gt;标记/整理算法&gt;标记/清除算法（此处的效率只是简单的对比时间复杂度，实际情况不一定如此）。</p>
</li>
<li><p>内存整齐度：复制算法=标记/整理算法&gt;标记/清除算法。</p>
</li>
<li><p>内存利用率：标记/整理算法=标记/清除算法&gt;复制算法。</p>
</li>
</ul>
<h3 id="垃圾回收算法的应用"><a href="#垃圾回收算法的应用" class="headerlink" title="垃圾回收算法的应用"></a>垃圾回收算法的应用</h3><ul>
<li><p>在新生代，使用的是复制算法（优化后的复制算法，采用Eden和survivor区。）通常e:s0:s1为8:1:1。因此只会浪费10%的内存用于复制回收。这个比例参照IBM统计的对象存活时间。因为大多数对象朝生夕死，且对象大小也有控制。因此这个优化的复制算法，即拥有复制算法中对内存碎片的整理功能，又有效的解决了内存浪费的问题。</p>
</li>
<li><p>在老年代使用的是标记整理算法。因为老年代的对象内存都比较大，因此使用复制算法会浪费很大内存。采用标记清除算法，则会产生较多的内存碎片，因此采用标记整理算法。标记整理算法的效率比较低，这也是为什么老年代的fullGC会导致系统停止的重要原因，也是我们为什么要尽量避免老年代fullGC的原因。</p>
</li>
</ul>
<h2 id="类加载"><a href="#类加载" class="headerlink" title="类加载"></a>类加载</h2><p>类加载到虚拟机内存中到卸载出内存的生命周期为：加载、验证、准备、解析、初始化、使用、卸载；七个阶段<br><img src="/blog/images/java/jvm/class_live.jpg"></p>
<ul>
<li>加载：JVM加载本地class文件</li>
<li>验证：验证加载的class文件的安全性，是否对JVM产生影响</li>
<li>准备：主要为类中的静态成员变量赋初始值。eg:（private static int age = 20）此时age并不是赋值为20，而是int的初始值：0</li>
<li>解析：将符号引用初始初始化为直接引用</li>
<li>初始化：这个阶段调用程序自定义代码。为静态成员变量赋其对应的值。eg：age=20。jvm只会对类初始化一次，并且不确定初始化的具体时机。但如下五种情况下，JVM会立即初始化clas</li>
</ul>
<ol>
<li>遇到new</li>
<li>反射</li>
<li>当初始化的类的父类没有初始化时，JVM会立即初始化其父类</li>
<li>虚拟机启动时，用户指定的主类。eg:（含有main方法的类）</li>
<li>J1.7动态类型中java.lang.invoke.MessageHandle生成的句柄对应的类</li>
</ol>
<h2 id="jvm监控工具"><a href="#jvm监控工具" class="headerlink" title="jvm监控工具"></a>jvm监控工具</h2><h3 id="jps"><a href="#jps" class="headerlink" title="jps"></a>jps</h3><p>查看所有的java进程<br><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">C:\Users\Administrator&gt;jps</span><br><span class="line">3888 Program</span><br><span class="line">4512</span><br><span class="line">10260 JConsole</span><br><span class="line">10420 Bootstrap</span><br><span class="line">10932</span><br><span class="line">12564 Jps</span><br></pre></td></tr></table></figure></p>
<h3 id="jinfo"><a href="#jinfo" class="headerlink" title="jinfo"></a>jinfo</h3><p>查看、设置某个参数的值<br><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">C:\Users\Administrator&gt;jinfo</span><br><span class="line">Usage:</span><br><span class="line">    jinfo [option] &lt;pid&gt;</span><br><span class="line">        (to connect to running process)</span><br><span class="line">    jinfo [option] &lt;executable &lt;core&gt;</span><br><span class="line">        (to connect to a core file)</span><br><span class="line">    jinfo [option] [server_id@]&lt;remote server IP or hostname&gt;</span><br><span class="line">        (to connect to remote debug server)</span><br><span class="line"></span><br><span class="line">where &lt;option&gt; is one of:</span><br><span class="line">    -flag &lt;name&gt;         to print the value of the named VM flag</span><br><span class="line">    -flag [+|-]&lt;name&gt;    to enable or disable the named VM flag</span><br><span class="line">    -flag &lt;name&gt;=&lt;value&gt; to set the named VM flag to the given value</span><br><span class="line">    -flags               to print VM flags</span><br><span class="line">    -sysprops            to print Java system properties</span><br><span class="line">    &lt;no option&gt;          to print both of the above</span><br><span class="line">    -h | -help           to print this help message</span><br></pre></td></tr></table></figure></p>
<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">C:\Users\Administrator&gt;jinfo -flags 3888</span><br><span class="line">Attaching to process ID 3888, please wait...</span><br><span class="line">Debugger attached successfully.</span><br><span class="line">Server compiler detected.</span><br><span class="line">JVM version is 25.131-b11</span><br><span class="line">Non-default VM flags: -XX:CICompilerCount=3 -XX:InitialHeapSize=536870912 -XX:MaxHeapSize=1073741824 -XX:MaxNewSize=357564416 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=178782208 -XX:OldSize=358088704 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC</span><br><span class="line">Command line:  -Dosgi.requiredJavaVersion=1.6 -Xms512m -Xmx1024m</span><br></pre></td></tr></table></figure>
<h3 id="jstat"><a href="#jstat" class="headerlink" title="jstat"></a>jstat</h3><p>java virtual machine statistics monitoring tool。利用JVM内建指令对java应用程序的资源和性能进行实时的命令行的监控，包括对Heap size和立即回收状况的监控。<br>jstat <option>（选项，命令工具） vmid（虚拟机的进程号） interval（间隔时间） count（打印次数）</option></p>
<ol>
<li>jstat -gcutil pid 总结垃圾回收统计<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">JDK7</span><br><span class="line">D:\Program Soft\Java\jdk1.7.0_80\bin&gt;jstat.exe -gcutil 3888 1000 5</span><br><span class="line">  S0     S1     E      O      P     YGC     YGCT    FGC    FGCT     GCT</span><br><span class="line">  0.00   0.00   2.05  57.89      ?   5626   86.993  5104 1753.905 1840.898</span><br><span class="line">  0.00   0.00   2.05  57.89      ?   5626   86.993  5104 1753.905 1840.898</span><br><span class="line">  0.00   0.00   2.05  57.89      ?   5626   86.993  5104 1753.905 1840.898</span><br><span class="line">  0.00   0.00   2.05  57.89      ?   5626   86.993  5104 1753.905 1840.898</span><br><span class="line">  0.00   0.00   2.05  57.89      ?   5626   86.993  5104 1753.905 1840.898</span><br><span class="line"></span><br><span class="line">JDK8</span><br><span class="line">D:\Program Soft\Java\jdk1.8.0_131\bin&gt;jstat.exe -gcutil 3888</span><br><span class="line">  S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT</span><br><span class="line">  0.00   0.00   2.05  57.89  93.45  85.97   5627   86.998  5105 1754.267 1841.265</span><br><span class="line"></span><br><span class="line">JDK9</span><br><span class="line">D:\Program Soft\Java\jdk-9.0.4\bin&gt;jstat.exe -gcutil 3888</span><br><span class="line">  S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT</span><br><span class="line">  0.00   0.00   2.05  57.89  93.45  85.97   5628   87.004  5106 1754.633 1841.636</span><br><span class="line"></span><br><span class="line">JDK10</span><br><span class="line">C:\Users\Administrator&gt;jstat -gcutil 3888</span><br><span class="line">  S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT</span><br><span class="line">  0.00   0.00   2.05  57.89  93.45  85.97   5628   87.004  5106 1754.633 1841.636</span><br></pre></td></tr></table></figure>
</li>
</ol>
<p>可以看出从JDK8开始JVM就去掉了Permgen永久代。增加了Metaspace元空间。具体细节不在此讨论！大致的可以看出jstat打印的的JVM信息有：</p>
<ul>
<li>S0：Heap上Survivor space 0 区已使用空间的百分比。</li>
<li>S1：Heap上Survivor space 1 区已使用空间的百分比。</li>
<li>E： Heap上Eden space区已使用空间的百分比。</li>
<li>O：Heap上  Old space区已使用空间的百分比。</li>
<li>P：Permgen区已使用空间的百分比（已废弃）。</li>
<li>YGC：应用程序启动到采样时发生的 Young GC (年轻代发生的GC)的次数</li>
<li>YGCT：应用程序启动到采样时发生的 Young GC所使用的时间（单位秒）</li>
<li>FGC：应用程序启动到采样时发生的 Full GC 的次数</li>
<li>FGCT：应用程序启动到采样时发生的 Full GC所使用的时间（单位秒）</li>
<li>GCT： 应用程序启动到采样时发生的 GC所使用的总时间（单位秒）</li>
<li>M：元空间Metaspace使用百分比。包括（Klass Metaspace 以及NoKlass Metaspace）</li>
<li>CCS；NoKlass Metaspace的使用率，也就是CCSU/CCSC算出来的</li>
</ul>
<ol>
<li><p>jstat -class vmid 类加载统计</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">C:\Users\Administrator&gt;jstat -class 3888</span><br><span class="line">Loaded  Bytes  Unloaded  Bytes     Time</span><br><span class="line"> 30579 60954.7      906  1322.2     200.52</span><br></pre></td></tr></table></figure>
</li>
<li><p>jstat -compiler vmid 编译统计</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">C:\Users\Administrator&gt;jstat -compiler 3888</span><br><span class="line">Compiled Failed Invalid   Time   FailedType FailedMethod</span><br><span class="line">   62389      4       0   540.16          1 org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding computeId</span><br></pre></td></tr></table></figure>
</li>
<li><p>jstat -gccapacity vmid 堆内存统计</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">jdk7</span><br><span class="line">D:\Program Soft\Java\jdk1.7.0_80\bin&gt;jstat.exe -gccapacity 3888</span><br><span class="line"> NGCMN    NGCMX     NGC     S0C   S1C       EC      OGCMN      OGCMX       OGC         OC      PGCMN    PGCMX     PGC       PC     YGC    FGC</span><br><span class="line">174592.0 349184.0 194048.0 1536.0 1024.0 190976.0   349696.0   699392.0   699392.0   699392.0        ?        ?        ?        ?   5650  5128</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">jdk 8 -jdk10</span><br><span class="line">C:\Users\Administrator&gt;jstat -gccapacity 3888</span><br><span class="line"> NGCMN    NGCMX     NGC     S0C   S1C       EC      OGCMN      OGCMX       OGC         OC       MCMN     MCMX      MC     CCSMN    CCSMX     CCSC    YGC    FGC</span><br><span class="line">174592.0 349184.0 193024.0 1024.0 1024.0 190976.0   349696.0   699392.0   699392.0   699392.0      0.0 1228800.0 205272.0      0.0 1048576.0  25560.0   5648  5126</span><br></pre></td></tr></table></figure>
</li>
</ol>
<ul>
<li>NGCMN       新生代最小容量</li>
<li>NGCMX       新生代最大容量</li>
<li>NGC         当前新生代容量</li>
<li>S0C         survivor0内存占用量</li>
<li>S1C         survivor1内存占用量</li>
<li>EC          eden区内存占用量</li>
<li>OGCMN       old区最小占用量</li>
<li>OGCMX       old区内存最大占用量</li>
<li>OGC         old内存当前新生成的内存占用量</li>
<li>OC          OC是old内存的占用量</li>
<li>PGCMN       PGCMN显示的是最小perm的内存使用量（废弃）</li>
<li>PGCMX       PGCMX显示的是perm的内存最大使用量（废弃）</li>
<li>PGC         PGC是当前新生成的perm内存占用量（废弃）</li>
<li>PC          永久代占用量（废弃）</li>
<li>YGC         Young GC次数</li>
<li>FGC         Full GC次数、</li>
<li>MCMN        metaspace区最小占用量</li>
<li>MCMX        metaspace区最大占用量</li>
<li>MC          metaspace区当前占用量</li>
<li>CCSMN       NoKlass Metaspace区最小占用量</li>
<li>CCSMX       NoKlass Metaspace区最大占用量</li>
<li>CCSC        NoKlass Metaspace区占用量</li>
</ul>
<p>jstat还可以对对应的内存区域的信息进行查询。如 jstat -gcnew vmid、 jstat -gcold vmid、 jstat -gcnewcapacity vmid等</p>
<p>jstat -options查看所有的操作<br><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">C:\Users\Administrator&gt;jstat -options</span><br><span class="line">-class</span><br><span class="line">-compiler</span><br><span class="line">-gc</span><br><span class="line">-gccapacity</span><br><span class="line">-gccause</span><br><span class="line">-gcmetacapacity 元数据内存统计</span><br><span class="line">-gcnew          新生代垃圾回收统计</span><br><span class="line">-gcnewcapacity  新生代内存统计</span><br><span class="line">-gcold          老年代垃圾回收统计</span><br><span class="line">-gcoldcapacity  老年代内存统计</span><br><span class="line">-gcutil</span><br><span class="line">-printcompilation jvm编译方法统计</span><br></pre></td></tr></table></figure></p>
<h3 id="jstack"><a href="#jstack" class="headerlink" title="jstack"></a>jstack</h3><ol>
<li><p>jstack 是用来查看java线程的调用堆栈工具（stack堆栈）。主要用来分析线程问题（死锁）。</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">C:\Users\Administrator&gt;jstack --help</span><br><span class="line">Usage:</span><br><span class="line">    jstack [-l] &lt;pid&gt;</span><br><span class="line">        (to connect to running process)</span><br><span class="line">    jstack -F [-m] [-l] &lt;pid&gt;</span><br><span class="line">        (to connect to a hung process)</span><br><span class="line">    jstack [-m] [-l] &lt;executable&gt; &lt;core&gt;</span><br><span class="line">        (to connect to a core file)</span><br><span class="line">    jstack [-m] [-l] [server_id@]&lt;remote server IP or hostname&gt;</span><br><span class="line">        (to connect to a remote debug server)</span><br><span class="line"></span><br><span class="line">Options:</span><br><span class="line">    -F  to force a thread dump. Use when jstack &lt;pid&gt; does not respond (process is hung)</span><br><span class="line">    当 jstack [-l] pid 没有响应的时候，强制打栈信息；一般情况不需要使用。</span><br><span class="line">    -m  to print both java and native frames (mixed mode)</span><br><span class="line">    打印java和native c/c++框架的所有栈信息，可打印JVM栈，显示上Native的栈帧，一般排查不需要。</span><br><span class="line">    -l  long listing. Prints additional information about locks</span><br><span class="line">    长列表， 打印关于锁的附加信息，会造成JVM停顿很长时间，一般不建议使用。</span><br><span class="line">    -h or -help to print this help message</span><br></pre></td></tr></table></figure>
</li>
<li><p>jstack输出的线程信息主要包含：JVM自身线程，用户线程等。jstack输出的线程信息，可以看出哪些线程在长时间占用cpu，尽快定位问题和解决问题</p>
</li>
</ol>
<h4 id="线程与Monitor的关系"><a href="#线程与Monitor的关系" class="headerlink" title="线程与Monitor的关系"></a>线程与Monitor的关系</h4><p>Monitor是java中用于实现线程之间互斥与协作的主要手段。Synchronize就是Monitor的实现。线程之间是怎样实现同步，以及状态是如何转换？<br><img src="/blog/images/java/jvm/thread_monitor.bmp"></p>
<ol>
<li><p><strong>进入区（Entry Set）</strong><br>线程请求获取对象锁时如果锁未被占有，则对象获取锁进入到<strong>拥有区</strong>，如果此时锁被其他线程占有，则进入到<strong>进入区</strong>等待锁。</p>
</li>
<li><p><strong>拥有者（The Owner）</strong><br>线程成功竞争到对象锁</p>
</li>
<li><p><strong>等待区（Wait Set）</strong><br>线程通过wait方法，释放对象的锁，并在等待区等待被唤醒。（已经获取过对象锁）</p>
</li>
</ol>
<h4 id="dump日志关于线程的修饰"><a href="#dump日志关于线程的修饰" class="headerlink" title="dump日志关于线程的修饰"></a>dump日志关于线程的修饰</h4><p>locked &lt;地址&gt; 目标：使用synchronized申请对象锁成功,监视器的拥有者。</p>
<p>waiting to lock &lt;地址&gt; 目标：使用synchronized申请对象锁未成功,在迚入区等待。</p>
<p>waiting on &lt;地址&gt; 目标：使用synchronized申请对象锁成功后,释放锁幵在等待区等待。</p>
<p>parking to wait for &lt;地址&gt; 目标<br>park是基本的线程阻塞原语,不通过监视器在对象上阻塞。随concurrent包会出现的新的机制,不synchronized体系不同。</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">&quot;Reference Handler&quot; #2 daemon prio=10 os_prio=2 tid=0x000000005464d800 nid=0x1634 in Object.wait() [0x000000005594f000]</span><br><span class="line">   java.lang.Thread.State: WAITING (on object monitor)</span><br><span class="line">        at java.lang.Object.wait(Native Method)</span><br><span class="line">        - waiting on &lt;0x00000000f3e958e8&gt; (a java.lang.ref.Reference$Lock)</span><br><span class="line">        at java.lang.Object.wait(Object.java:502)</span><br><span class="line">        at java.lang.ref.Reference.tryHandlePending(Reference.java:191)</span><br><span class="line">        - locked &lt;0x00000000f3e958e8&gt; (a java.lang.ref.Reference$Lock)</span><br><span class="line">        at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)</span><br><span class="line"></span><br><span class="line">&quot;DestroyJavaVM&quot; #12 prio=5 os_prio=0 tid=0x000000000253c000 nid=0x3188 waiting on condition [0x0000000000000000]</span><br><span class="line">   java.lang.Thread.State: RUNNABLE</span><br></pre></td></tr></table></figure>
<h4 id="分析dump方法"><a href="#分析dump方法" class="headerlink" title="分析dump方法"></a>分析dump方法</h4><p>wait on monitor entry： 被阻塞的,肯定有问题</p>
<p>runnable ： 注意IO线程</p>
<p>in Object.wait()： 注意非线程池等待</p>
<p>分析dump时注意死锁的发生。发生死锁时一定有一个线程lock一个锁1并且在waiting to lock另外一个锁2；而另外一个线程lock锁2，并且在wait to lock锁1。这样就是明显的死锁dump信息。</p>
<p>虚拟机执行Full GC时,会阻塞所有的用户线程。因此,即时获取到同步锁的线程也有可能被阻塞。 在查看线程Dump时,首先查看内存使用情况。</p>
<h3 id="jmap"><a href="#jmap" class="headerlink" title="jmap"></a>jmap</h3><p>java提供的查看<strong>java程序的内存分配详情</strong>工具。例如实例个数，大小等。可以使用jmap来生成heapdump<br><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">（JDK1.8版本）</span><br><span class="line">C:\Users\Administrator&gt;jmap --help</span><br><span class="line">Usage:</span><br><span class="line">    jmap [option] &lt;pid&gt;</span><br><span class="line">        (to connect to running process)</span><br><span class="line">    jmap [option] &lt;executable &lt;core&gt;</span><br><span class="line">        (to connect to a core file)</span><br><span class="line">    jmap [option] [server_id@]&lt;remote server IP or hostname&gt;</span><br><span class="line">        (to connect to remote debug server)</span><br><span class="line"></span><br><span class="line">where &lt;option&gt; is one of:</span><br><span class="line">    &lt;none&gt;               to print same info as Solaris pmap</span><br><span class="line">    -heap                to print java heap summary</span><br><span class="line">    -histo[:live]        to print histogram of java object heap; if the &quot;live&quot;</span><br><span class="line">                         suboption is specified, only count live objects</span><br><span class="line">    -clstats             to print class loader statistics</span><br><span class="line">    -finalizerinfo       to print information on objects awaiting finalization</span><br><span class="line">    -dump:&lt;dump-options&gt; to dump java heap in hprof binary format</span><br><span class="line">                         dump-options:</span><br><span class="line">                           live         dump only live objects; if not specified,</span><br><span class="line">                                        all objects in the heap are dumped.</span><br><span class="line">                           format=b     binary format</span><br><span class="line">                           file=&lt;file&gt;  dump heap to &lt;file&gt;</span><br><span class="line">                         Example: jmap -dump:live,format=b,file=heap.bin &lt;pid&gt;</span><br><span class="line">    -F                   force. Use with -dump:&lt;dump-options&gt; &lt;pid&gt; or -histo</span><br><span class="line">                         to force a heap dump or histogram when &lt;pid&gt; does not</span><br><span class="line">                         respond. The &quot;live&quot; suboption is not supported</span><br><span class="line">                         in this mode.</span><br><span class="line">    -h | -help           to print this help message</span><br><span class="line">    -J&lt;flag&gt;             to pass &lt;flag&gt; directly to the runtime system</span><br></pre></td></tr></table></figure></p>
<ul>
<li>heap：打印heapd 概要信息：GC使用算法，heap的配置以及wise heap的使用情况。</li>
<li>histo：打印每个class的实例数目，内存占用，类全名信息。live参数表示只打印存活的对象</li>
<li>finalizerinfo：打印正在等待回收的对象</li>
<li>-dump：使用hprof二进制形式，输出JVM的heap内容到文件。导出的dump文件需要使用dump文件查看工具进行查看</li>
</ul>
<h4 id="heap"><a href="#heap" class="headerlink" title="heap"></a>heap</h4><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">C:\Users\Administrator&gt;jmap -heap 6664</span><br><span class="line">Attaching to process ID 6664, please wait...</span><br><span class="line">Debugger attached successfully.</span><br><span class="line">Server compiler detected.</span><br><span class="line">JVM version is 25.131-b11</span><br><span class="line"></span><br><span class="line">using thread-local object allocation.</span><br><span class="line">Parallel GC with 4 thread(s)</span><br><span class="line"></span><br><span class="line">Heap Configuration:</span><br><span class="line">   MinHeapFreeRatio         = 0</span><br><span class="line">   MaxHeapFreeRatio         = 100</span><br><span class="line">   MaxHeapSize              = 2126512128 (2028.0MB)</span><br><span class="line">   NewSize                  = 44564480 (42.5MB)</span><br><span class="line">   MaxNewSize               = 708837376 (676.0MB)</span><br><span class="line">   OldSize                  = 89653248 (85.5MB)</span><br><span class="line">   NewRatio                 = 2</span><br><span class="line">   SurvivorRatio            = 8</span><br><span class="line">   MetaspaceSize            = 21807104 (20.796875MB)</span><br><span class="line">   CompressedClassSpaceSize = 1073741824 (1024.0MB)</span><br><span class="line">   MaxMetaspaceSize         = 17592186044415 MB</span><br><span class="line">   G1HeapRegionSize         = 0 (0.0MB)</span><br><span class="line"></span><br><span class="line">Heap Usage:</span><br><span class="line">PS Young Generation</span><br><span class="line">Eden Space:</span><br><span class="line">   capacity = 159907840 (152.5MB)</span><br><span class="line">   used     = 136378944 (130.06109619140625MB)</span><br><span class="line">   free     = 23528896 (22.43890380859375MB)</span><br><span class="line">   85.28596471567623% used</span><br><span class="line">From Space:</span><br><span class="line">   capacity = 11534336 (11.0MB)</span><br><span class="line">   used     = 6566184 (6.262001037597656MB)</span><br><span class="line">   free     = 4968152 (4.737998962402344MB)</span><br><span class="line">   56.927282159978695% used</span><br><span class="line">To Space:</span><br><span class="line">   capacity = 11010048 (10.5MB)</span><br><span class="line">   used     = 0 (0.0MB)</span><br><span class="line">   free     = 11010048 (10.5MB)</span><br><span class="line">   0.0% used</span><br><span class="line">PS Old Generation</span><br><span class="line">   capacity = 73400320 (70.0MB)</span><br><span class="line">   used     = 27605144 (26.326316833496094MB)</span><br><span class="line">   free     = 45795176 (43.673683166503906MB)</span><br><span class="line">   37.60902404785156% used</span><br><span class="line"></span><br><span class="line">26711 interned Strings occupying 3197744 bytes.</span><br></pre></td></tr></table></figure>
<p>这个命令可以看出heap对的一些配置信息以及使用情况。例如</p>
<ul>
<li>使用TLAB（using thread-local object allocation.）</li>
<li>使用了并行的垃圾回收器，并且启动了4个线程来GC</li>
<li>Heap对的几个区域的使用情况：总容量，已使用容量，空余容量</li>
</ul>
<h4 id="histo"><a href="#histo" class="headerlink" title="histo"></a>histo</h4><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">&gt; jmap -histo:live 6664</span><br><span class="line">...... 省略</span><br><span class="line">4793:             1             16  sun.rmi.transport.DGCImpl_Skel</span><br><span class="line">4794:             1             16  sun.rmi.transport.DGCImpl_Stub</span><br><span class="line">4795:             1             16  sun.rmi.transport.proxy.RMIDirectSocketFactory</span><br><span class="line">4796:             1             16  sun.rmi.transport.tcp.TCPTransport$1</span><br><span class="line">4797:             1             16  sun.security.provider.NativeSeedGenerator</span><br><span class="line">4798:             1             16  sun.security.util.AlgorithmDecomposer</span><br><span class="line">4799:             1             16  sun.security.util.DisabledAlgorithmConstraints$Constraints</span><br><span class="line">4800:             1             16  sun.util.calendar.Gregorian</span><br><span class="line">4801:             1             16  sun.util.locale.provider.AuxLocaleProviderAdapter$NullProvider</span><br><span class="line">4802:             1             16  sun.util.locale.provider.CalendarDataUtility$CalendarWeekParameterGetter</span><br><span class="line">4803:             1             16  sun.util.locale.provider.SPILocaleProviderAdapter</span><br><span class="line">4804:             1             16  sun.util.locale.provider.TimeZoneNameUtility$TimeZoneNameGetter</span><br><span class="line">4805:             1             16  sun.util.resources.LocaleData</span><br><span class="line">4806:             1             16  sun.util.resources.LocaleData$LocaleDataResourceBundleControl</span><br><span class="line">Total        500778       30369512</span><br></pre></td></tr></table></figure>
<p>该命令打印了jvm中类对应的对象的个数。加上:live则只打印存活的对象</p>
<h4 id="dump"><a href="#dump" class="headerlink" title="dump"></a>dump</h4><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">C:\Users\Administrator&gt;jmap -dump:format=b,file=heap.bin 6664</span><br><span class="line">Dumping heap to C:\Users\Administrator\heap.bin ...</span><br><span class="line">Heap dump file created</span><br></pre></td></tr></table></figure>
<p>这里注意一下：dump的参数之间不需要加上空格，format=b,file=beap.bin否则命令失败<br>我们的dump文件已经生产并且默认保存路径为：C:\Users\Administrator\heap.bin<br>然后用Eclipse的MAT插件打开（没安装插件需要先安装），引入Eclipse后可看到统计图表<br><img src="/blog/images/java/jvm/jvm_heap_dump_1.png"><br>这个图具体怎么解读，也不是太清楚，以后使用再总结。</p>
<h3 id="JConsole"><a href="#JConsole" class="headerlink" title="JConsole"></a>JConsole</h3><p>待续</p>
<h3 id="VisualVM"><a href="#VisualVM" class="headerlink" title="VisualVM"></a>VisualVM</h3><p>待续</p>
<h2 id="JVM问题分析"><a href="#JVM问题分析" class="headerlink" title="JVM问题分析"></a>JVM问题分析</h2><h3 id="频繁GC问题"><a href="#频繁GC问题" class="headerlink" title="频繁GC问题"></a>频繁GC问题</h3><p>一、使用jps查看线程ID</p>
<p>二、使用jstat -gc 3331 250 20 查看gc情况，一般比较关注PERM区的情况，查看GC的增长情况。</p>
<p>三、使用jstat -gccause：额外输出上次GC原因</p>
<p>四、使用jmap -dump:format=b,file=heapDump 3331生成堆转储文件</p>
<p>五、使用jhat或者可视化工具（Eclipse Memory Analyzer 、IBM HeapAnalyzer）分析堆情况。</p>
<p>六、结合代码解决内存溢出或泄露问题。</p>
<p>jvm出现的致命错误，会在默认工作目录下面生成了hs_err_pid<pid>.log 日志文件。其中包含了导致jvm crash 的重要信息（我们可以在虚拟参数中添加 -XX:ErrorFie=./hss_err_pid<pid>.log指定生成路径。）</pid></pid></p>
<h3 id="死锁问题"><a href="#死锁问题" class="headerlink" title="死锁问题"></a>死锁问题</h3><p>一、使用jps查看线程ID</p>
<p>二、使用jstack 3331：查看线程情况</p>
<h3 id="JVM调优-1"><a href="#JVM调优-1" class="headerlink" title="JVM调优"></a>JVM调优</h3><p>JVM调优的主要目的是降低youngGC的评率，减少fullGC的次数。调优手段有：</p>
<ul>
<li>1.新生代设置过小</li>
</ul>
<ol>
<li>新生代容易占满，导致新生代GC（youngGC）次数非常频繁，增大系统消耗； </li>
<li>是大对象直接进入老生代，占据了老年代剩余空间，诱发fullGC。 </li>
</ol>
<ul>
<li>2.新生代设置过大 </li>
</ul>
<ol>
<li>新生代设置过大会导致老年代过小（堆总量一定），从而诱发fullGC。 </li>
<li>新生代GC耗时大幅度增加。 </li>
<li>一般说来新生代占整个堆1/3比较合适。</li>
</ol>
<ul>
<li>3.survivor设置过小</li>
</ul>
<ol>
<li>生代中根据优化复制算法，如果Survivor区（S0，S1）太小，会导致对象从eden区直接到达老年代，降低了在新生代的存活时间。一般来说Eden:S0:S1为8:1:1是比较合理的。 </li>
</ol>
<ul>
<li>4.survivor设置过大</li>
</ul>
<ol>
<li>若Survivor区过大，则eden区会过小，eden区容易达到阈值导致新生代GC频率增加。</li>
</ol>
<ul>
<li>5.新生代对象存活时间过短 </li>
</ul>
<ol>
<li>通过-XX:MaxTenuringThreshold=n来控制老年代存活时间，如果存活时间过短，则对象会很快进入老年 代，导致fullGC。所以要尽量让不常用对象在新生代被回收。</li>
</ol>
<h3 id="FullGC何时发生"><a href="#FullGC何时发生" class="headerlink" title="FullGC何时发生"></a>FullGC何时发生</h3><ul>
<li><p>1.老年代空间不足<br>尽量让对象多停留在新生代，增加对象存活年龄–XX:MaxTenuringThreshold的设置；或是增加新生代对象大小–XX：PretenureSizeThreshold的设置。或是调整jvm堆大小xms,xmx的大小</p>
</li>
<li><p>2.Permanet Generation 空间不足<br>方法区内存不足，查看是否因为加载过多的Class，使用小巧的API，或者是是否因为创建过多的静态变量。</p>
</li>
<li><p>3.GC晋升到老年代的平均大小大于老年代剩余空间<br>控制好新生代和老年代的比例</p>
</li>
<li><p>System.gc()调用<br>尽量不要手动调用该方法，让JVM自行进行垃圾回收</p>
</li>
</ul>
<blockquote>
<p>参考<br><a href="http://ifeve.com/java-permgen-removed/" target="_blank" rel="external">Java Perm到MetaSpace</a><br><a href="http://blog.csdn.net/qq_23835497/article/details/71696067" target="_blank" rel="external">Java的新生代，老年代，永久代</a><br><a href="https://blog.csdn.net/maosijunzi/article/details/46049117" target="_blank" rel="external">jstat命令使用</a><br><a href="http://www.hollischuang.com/archives/110" target="_blank" rel="external">jstack命令使用</a><br><a href="https://www.jianshu.com/p/92a5fbb33764" target="_blank" rel="external">Metaspace分析</a><br><a href="https://blog.csdn.net/rachel_luo/article/details/8992461" target="_blank" rel="external">性能分析工具之– Eclipse Memory Analyzer tool(MAT)</a></p>
</blockquote>

      
    </div>

    <div>
      
        

      
    </div>

    <div>
      
        

      
    </div>


    <footer class="post-footer">
      
        <div class="post-tags">
          
            <a href="/blog/tags/java/" rel="tag"># java</a>
          
            <a href="/blog/tags/jvm/" rel="tag"># jvm</a>
          
        </div>
      

      
        
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/blog/2017/12/21/redis集群模式的容错扩容/" rel="next" title="redis集群模式的容错扩容">
                <i class="fa fa-chevron-left"></i> redis集群模式的容错扩容
              </a>
            
          </div>

          <span class="post-nav-divider"></span>

          <div class="post-nav-prev post-nav-item">
            
              <a href="/blog/2017/12/26/logstash安装/" rel="prev" title="logstash安装">
                logstash安装 <i class="fa fa-chevron-right"></i>
              </a>
            
          </div>
        </div>
      

      
      
    </footer>
  </article>



    <div class="post-spread">
      
    </div>
  </div>

          
          </div>
          


          
  <div class="comments" id="comments">
    
      <div id="lv-container" data-id="city" data-uid="MTAyMC8zNjY5NS8xMzIzMA=="></div>
    
  </div>


        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap" >
            文章目录
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview">
            站点概览
          </li>
        </ul>
      

      <section class="site-overview sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
          <img class="site-author-image" itemprop="image"
               src="/blog/images/head.jpg"
               alt="Fang ShuHao" />
          <p class="site-author-name" itemprop="name">Fang ShuHao</p>
           
              <p class="site-description motion-element" itemprop="description"></p>
          
        </div>
        <nav class="site-state motion-element">
        
          
            <div class="site-state-item site-state-posts">
              <a href="/blog/archives">
                <span class="site-state-item-count">135</span>
                <span class="site-state-item-name">日志</span>
              </a>
            </div>
          

          
            <div class="site-state-item site-state-categories">
              <a href="/blog/categories">
                <span class="site-state-item-count">35</span>
                <span class="site-state-item-name">分类</span>
              </a>
            </div>
          

          
            <div class="site-state-item site-state-tags">
              <a href="/blog/tags">
                <span class="site-state-item-count">93</span>
                <span class="site-state-item-name">标签</span>
              </a>
            </div>
          

        </nav>

        

        <div class="links-of-author motion-element">
          
        </div>

        
        

        
        

        


      </section>

      
      <!--noindex-->
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">

            
              
            

            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-2"><a class="nav-link" href="#JVM参数"><span class="nav-number">1.</span> <span class="nav-text">JVM参数</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#JVM各个参数的含义"><span class="nav-number">1.1.</span> <span class="nav-text">JVM各个参数的含义</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#JVM调优"><span class="nav-number">1.2.</span> <span class="nav-text">JVM调优</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#java-YoungGen、OldGen、PermGen"><span class="nav-number">2.</span> <span class="nav-text">java YoungGen、OldGen、PermGen</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#年轻代-YoungGen"><span class="nav-number">2.1.</span> <span class="nav-text">年轻代 YoungGen</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#老年代-OldGen"><span class="nav-number">2.2.</span> <span class="nav-text">老年代 OldGen</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#永久代-PermGen"><span class="nav-number">2.3.</span> <span class="nav-text">永久代 PermGen</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#java-heap-堆"><span class="nav-number">3.</span> <span class="nav-text">java heap 堆</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#CodeCache"><span class="nav-number">4.</span> <span class="nav-text">CodeCache</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#JVM-编译模式"><span class="nav-number">4.1.</span> <span class="nav-text">JVM 编译模式</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#JIT编译"><span class="nav-number">4.2.</span> <span class="nav-text">JIT编译</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#编译参数"><span class="nav-number">4.2.1.</span> <span class="nav-text">编译参数</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Java对象创建的过程"><span class="nav-number">4.3.</span> <span class="nav-text">Java对象创建的过程</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#jdk8去掉PermGen新增Metaspace的好处"><span class="nav-number">5.</span> <span class="nav-text">jdk8去掉PermGen新增Metaspace的好处</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Metaspace的不足"><span class="nav-number">6.</span> <span class="nav-text">Metaspace的不足</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#垃圾收集算法"><span class="nav-number">7.</span> <span class="nav-text">垃圾收集算法</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#标记清除算法"><span class="nav-number">7.1.</span> <span class="nav-text">标记清除算法</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#复制算法"><span class="nav-number">7.2.</span> <span class="nav-text">复制算法</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#标记整理算法"><span class="nav-number">7.3.</span> <span class="nav-text">标记整理算法</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#垃圾回收算法的应用"><span class="nav-number">7.4.</span> <span class="nav-text">垃圾回收算法的应用</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#类加载"><span class="nav-number">8.</span> <span class="nav-text">类加载</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#jvm监控工具"><span class="nav-number">9.</span> <span class="nav-text">jvm监控工具</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#jps"><span class="nav-number">9.1.</span> <span class="nav-text">jps</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#jinfo"><span class="nav-number">9.2.</span> <span class="nav-text">jinfo</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#jstat"><span class="nav-number">9.3.</span> <span class="nav-text">jstat</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#jstack"><span class="nav-number">9.4.</span> <span class="nav-text">jstack</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#线程与Monitor的关系"><span class="nav-number">9.4.1.</span> <span class="nav-text">线程与Monitor的关系</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#dump日志关于线程的修饰"><span class="nav-number">9.4.2.</span> <span class="nav-text">dump日志关于线程的修饰</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#分析dump方法"><span class="nav-number">9.4.3.</span> <span class="nav-text">分析dump方法</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#jmap"><span class="nav-number">9.5.</span> <span class="nav-text">jmap</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#heap"><span class="nav-number">9.5.1.</span> <span class="nav-text">heap</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#histo"><span class="nav-number">9.5.2.</span> <span class="nav-text">histo</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#dump"><span class="nav-number">9.5.3.</span> <span class="nav-text">dump</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#JConsole"><span class="nav-number">9.6.</span> <span class="nav-text">JConsole</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#VisualVM"><span class="nav-number">9.7.</span> <span class="nav-text">VisualVM</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#JVM问题分析"><span class="nav-number">10.</span> <span class="nav-text">JVM问题分析</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#频繁GC问题"><span class="nav-number">10.1.</span> <span class="nav-text">频繁GC问题</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#死锁问题"><span class="nav-number">10.2.</span> <span class="nav-text">死锁问题</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#JVM调优-1"><span class="nav-number">10.3.</span> <span class="nav-text">JVM调优</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#FullGC何时发生"><span class="nav-number">10.4.</span> <span class="nav-text">FullGC何时发生</span></a></li></ol></li></ol></div>
            

          </div>
        </section>
      <!--/noindex-->
      

      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright" >
  
  &copy; 
  <span itemprop="copyrightYear">2019</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">Fang ShuHao</span>
</div>


<div class="powered-by">
  由 <a class="theme-link" href="https://hexo.io">Hexo</a> 强力驱动
</div>

<div class="theme-info">
  主题 -
  <a class="theme-link" href="https://github.com/iissnan/hexo-theme-next">
    NexT.Mist
  </a>
</div>


        

        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
      </div>
    
    
  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  




  
  <script type="text/javascript" src="/blog/lib/jquery/index.js?v=2.1.3"></script>

  
  <script type="text/javascript" src="/blog/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>

  
  <script type="text/javascript" src="/blog/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>

  
  <script type="text/javascript" src="/blog/lib/velocity/velocity.min.js?v=1.2.1"></script>

  
  <script type="text/javascript" src="/blog/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>

  
  <script type="text/javascript" src="/blog/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>


  


  <script type="text/javascript" src="/blog/js/src/utils.js?v=5.1.0"></script>

  <script type="text/javascript" src="/blog/js/src/motion.js?v=5.1.0"></script>



  
  

  
  <script type="text/javascript" src="/blog/js/src/scrollspy.js?v=5.1.0"></script>
<script type="text/javascript" src="/blog/js/src/post-details.js?v=5.1.0"></script>



  


  <script type="text/javascript" src="/blog/js/src/bootstrap.js?v=5.1.0"></script>



  



  




	





  





  





  
    <script type="text/javascript">
      (function(d, s) {
        var j, e = d.getElementsByTagName(s)[0];
        if (typeof LivereTower === 'function') { return; }
        j = d.createElement(s);
        j.src = 'https://cdn-city.livere.com/js/embed.dist.js';
        j.async = true;
        e.parentNode.insertBefore(j, e);
      })(document, 'script');
    </script>
  



  
  

  

  

  

  


  

</body>
</html>
